﻿using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Text;

namespace AB.Common
{
    /// <summary>
    /// Redis帮助类(ServiceStack.Redis)
    /// </summary>
    public class RedisClientHelper
    {
        /// <summary>
        /// 定义一个标识确保线程同步
        /// </summary>
        static readonly object locker = new object();
        /// <summary>
        /// 单例实例
        /// </summary>
        static RedisClientHelper Singleton = null;
        /// <summary>
        /// RedisClient
        /// </summary>
        RedisClient RedisClient = null;
        /// <summary>
        /// 禁用公共构造方法
        /// </summary>
        RedisClientHelper()
        {

        }
        /// <summary>
        /// 创建单例实例
        /// </summary>
        /// <returns></returns>
        public static RedisClientHelper Single()
        {
            if (Singleton == null)
            {
                lock (locker)
                {
                    if (Singleton == null)
                    {
                        Singleton = new RedisClientHelper();
                    }
                }
            }
            return Singleton;
        }
        /// <summary>
        /// 获取redisClient
        /// </summary>
        /// <returns></returns>
        RedisClient GetRedisClient()
        {
            if (RedisClient == null)
            {
                try
                {
                    string RedisHost = ConfigHelper.StringConfig("RedisHost");
                    int RedisPort = ConfigHelper.IntConfig("RedisPort", -1);
                    string RedisPwd = ConfigHelper.StringConfig("RedisPwd");
                    if (string.IsNullOrEmpty(RedisHost) || RedisPort < 0 || string.IsNullOrEmpty(RedisPwd))
                    {
                        return null;
                    }
                    RedisClient = new RedisClient(RedisHost, RedisPort, RedisPwd);
                }
                catch (Exception ex)
                {
                    ABCommonDebug.WriteLine(ex);
                    return null;
                }
            }
            return RedisClient;
        }
        /// <summary>
        /// LPush
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool LPush(string key, string value)
        {
            try
            {
                GetRedisClient().LPush(key, GetBytes(value));
                return true;
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return false;
        }
        /// <summary>
        /// LPush(将对象转为json后存储)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool LPush(string key, object value)
        {
            try
            {
                return LPush(key, value.ABToJSON());
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return false;
        }
        /// <summary>
        /// RPush
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool RPush(string key, string value)
        {
            try
            {
                GetRedisClient().RPush(key, GetBytes(value));
                return true;
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return false;
        }
        /// <summary>
        /// RPush(将对象转为json后存储)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool RPush(string key, object value)
        {
            try
            {
                return RPush(key, value.ABToJSON());
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return false;
        }
        /// <summary>
        /// RPop
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string RPop(string key)
        {
            try
            {
                byte[] barry = GetRedisClient().RPop(key);
                if (barry != null)
                {
                    return GetString(barry);
                }
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return null;
        }
        /// <summary>
        /// RPop(取出对象，该对象类型必须具有公共无参构造函数)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T RPop<T>(string key) where T : class, new()
        {
            try
            {
                string str = RPop(key);
                if (!string.IsNullOrEmpty(str))
                {
                    return str.ABToObj<T>();
                }
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return null;
        }
        /// <summary>
        /// MultiRPop
        /// </summary>
        /// <param name="key"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public List<string> MultiRPop(string key, int num)
        {
            List<string> values = new List<string>();
            try
            {
                while (values.Count < num)
                {
                    string value = RPop(key);
                    if (value != null)
                    {
                        values.Add(value);
                    }
                    if (GetListCount(key) < 1)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return values;
        }
        /// <summary>
        /// MultiRPop
        /// </summary>
        /// <param name="key"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public List<T> MultiRPop<T>(string key, int num) where T : class, new()
        {
            List<T> values = new List<T>();
            try
            {
                while (values.Count < num)
                {
                    T value = RPop<T>(key);
                    if (value != null)
                    {
                        values.Add(value);
                    }
                    if (GetListCount(key) < 1)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return values;
        }
        /// <summary>
        /// Del
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Del(string key)
        {
            try
            {
                GetRedisClient().Del(key);
                return true;
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return false;
        }
        /// <summary>
        /// GetAllItemsFromList
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public List<string> GetAllItemsFromList(string key)
        {
            List<string> list = new List<string>();
            try
            {
                list = GetRedisClient().GetAllItemsFromList(key);
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return list;
        }
        /// <summary>
        /// GetAllKeys
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllKeys()
        {
            List<string> list = new List<string>();
            try
            {
                list = GetRedisClient().GetAllKeys();
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return list;
        }
        /// <summary>
        /// GetListCount
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long GetListCount(string key)
        {
            try
            {
                return GetRedisClient().GetListCount(key);
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return 0;
        }
        /// <summary>
        /// Type
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string Type(string key)
        {
            try
            {
                return GetRedisClient().Type(key);
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return string.Empty;
        }
        /// <summary>
        /// Add
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public bool Add<T>(string key, T value)
        {
            try
            {
                GetRedisClient().Add<T>(key, value);
                return true;
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return false;
        }
        /// <summary>
        /// AddRangeToList
        /// </summary>
        /// <param name="listId"></param>
        /// <param name="values"></param>
        public void AddRangeToList(string listId, List<string> values)
        {
            try
            {
                GetRedisClient().AddRangeToList(listId, values);
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
        }
        /// <summary>
        /// Get
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            try
            {
                return GetRedisClient().Get<T>(key);
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return default(T);
        }
        /// <summary>
        /// Remove
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Remove(string key)
        {
            try
            {
                return GetRedisClient().Remove(key);
            }
            catch (Exception ex)
            {
                ABCommonDebug.WriteLine(ex);
            }
            return false;
        }
        private byte[] GetBytes(string value)
        {
            return Encoding.UTF8.GetBytes(value);
        }
        private string GetString(byte[] value)
        {
            return Encoding.UTF8.GetString(value);
        }

    }
}
